<!DOCTYPE html>
<html>
    <body>
        <h3>AI五子棋游戏</h3>
        <canvas id="chess" width="450px" height="450px"></canvas>
        <script>
            var chressBord = []; //棋盘			
            var wins = [];  //存放所有5个棋子在一条线上所有可能性，第一维存放y, 第二维存放x，第三维存放当前的可能性编号
            var count = 0; //赢法总数量
            var myWin = []; //我们赢法的统计数组
            var computerWin = []; //计算机赢法的统计数组
            var chess = document.getElementById("chess");
            var context = chess.getContext('2d');
 
            for(var i = 0; i < 15; i++)
			{
                chressBord[i] = [];
                wins[i] = [];
                for(var j = 0; j < 15; j++)
				{
                    chressBord[i][j] = 0;
                    wins[i][j] = [];
                }
            }
			
            //横线赢法
            for(var i = 0; i < 15; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i][j+k][count] = true;
			
            //竖线赢法
            for(var i = 0; i < 15; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[j+k][i][count] = true;
			
            //正斜线赢法
            for(var i = 0; i < 11; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i+k][j+k][count] = true;
			
            //反斜线赢法
            for(var i = 0; i < 11; i++)  
                for(var j = 14; j > 3; j--,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i+k][j-k][count] = true;
			
            for(var i = 0; i < count; i++)
			{
                myWin[i] = 0; //这个数组很精髓，记录下棋后我方每一个位置在每种赢法的得分
                computerWin[i] = 0;
            }
            
            chess.onclick = function(e) // 我，下棋
			{
                var i = Math.floor(e.offsetX / 30);
                var j = Math.floor(e.offsetY / 30);
                if(chressBord[i][j] == 0)
				{
                    MoveStep(i,j,"red", 1, myWin);
                    computerAI();
                }         
            }
			
            // 计算机下棋，找玩家最容易赢的位置或者电脑最容易赢的位置
            var computerAI = function ()
			{
                var myScore = [];
                var computerScore = [];
                var max = 0;
                var u = 0, v = 0;
                for(var i = 0; i < 15; i++)
				{
                    myScore[i] = [];
                    computerScore[i] = [];
                    for(var j = 0; j < 15; j++)
					{
                        myScore[i][j] = 0;
                        computerScore[i][j] = 0;
                    }
                }
				
				//找落子赢的概率最大坐标
                for(var i = 0; i < 15; i++)
				{
                    for(var j = 0; j < 15; j++)
					{						
						for(var k = 0; k < count; k++) //遍历到i,j这个坐标时，计算谁的得分更高
						{
							if(chressBord[i][j] != 0 || !wins[i][j][k]) //当前i,j坐标还没落子
								continue;
							
							switch(myWin[k])
							{
								case 1: myScore[i][j] += 200; break;
								case 2: myScore[i][j] += 400; break;
								case 3: myScore[i][j] += 2000; break;
								case 4: myScore[i][j] += 10000; break;
							}
							
							switch(computerWin[k])
							{
								case 1: computerScore[i][j] += 220; break;
								case 2: computerScore[i][j] += 420; break;
								case 3: computerScore[i][j] += 2100; break;
								case 4: computerScore[i][j] += 20000; break;
							}
						}
						
						if(myScore[i][j] > max) //如果玩家落子的分数多，就替换
						{
							max  = myScore[i][j];
							u = i;
							v = j;
						}
						else if(myScore[i][j] == max)  //如果玩家落子的分数跟原来最多分数一样多
						{
							if(computerScore[i][j] > computerScore[u][v]) //如果电脑在i,j落子的分数比u,v的分数多，就替换
							{
								u = i;
								v = j;    
							}
						}
						
						if(computerScore[i][j] > max) //如果电脑下棋新位置分数比原来的多，就替换
						{
							max  = computerScore[i][j];
							u = i;
							v = j;
						}
						else if(computerScore[i][j] == max) //如果电脑下棋新位置分数跟原来的一样多
						{
							if(myScore[i][j] > myScore[u][v]) //如果玩家落子的分数多，就准备把玩家最好的位置占掉
							{
								u = i;
								v = j;    
							}
						}
                    }
                }
				
                MoveStep(u,v,"blue", 2, computerWin);
            }
			
			var CheckWin = function(i, j, Role, WinArray)
			{			
				for(var k = 0; k < count; k++)
					if(wins[i][j][k]) // 将可能赢的情况都加1
					{
						WinArray[k]++;
						if(WinArray[k] >= 5)
							alert(Role + ': 恭喜，你赢了！')
					}
			}
			
            //绘画棋盘
            var drawChessBoard = function() 
			{
                for(var i = 0; i < 15; i++)
				{
                    context.moveTo(15 + i * 30 , 15);
                    context.lineTo(15 + i * 30 , 435);
                    context.moveTo(15 , 15 + i * 30);
                    context.lineTo(435 , 15 + i * 30);
                    context.stroke();
                }
            }
			
            drawChessBoard(); // 画棋盘
            
            var MoveStep = function(i,j,Role, ID, WinArray) //落子
			{
                context.beginPath();
                context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);// 画圆
                context.closePath();    
                context.fillStyle = Role;
                context.fill(); //填充颜色
				
				chressBord[i][j] = ID; //玩家ID棋盘位置占位
				CheckWin(i,j,Role, WinArray);  //判断是否获胜，这里也很精髓，递归思想
            }
        </script>
    </body>
</html>